package com.chj.design.sk;

import java.util.ArrayList;
import java.util.List;

// https://juejin.cn/post/6844903924630028295
public class Code09_Visitor2 {
	// 定义抽象元素（英雄的模板）
	public static abstract class Hero {
		// 英雄可以接受玩家的访问，让玩家来操作
		public abstract void accept(Player visitor);
	}

	// 定义具体元素（具体某一个英雄）
	// 甄姬
	public static class ZhenHero extends Hero {
		// 可以接受玩家的操作
		@Override
		public void accept(Player visitor) {
			visitor.visitZhen(this);
		}

		// 自身的技能
		public void operate() {
			System.out.println("甄姬放出了技能");
		}
	}

	// 庄周
	public static class ZhuangHero extends Hero {
		// 接受外部的访问
		@Override
		public void accept(Player visitor) {
			visitor.visitZhuang(this);
		}

		// 自身的技能
		public void operate() {
			System.out.println("庄周放出了技能");
		}
	}

	// 定义抽象访问者（玩家）
	// 玩家可以访问甄姬和庄周的技能
	public interface Player {
		public abstract void visitZhuang(ZhuangHero element);

		public abstract void visitZhen(ZhenHero element);
	}

	// 定义具体访问者（玩家我和其他玩家）
	public static class PlayerMe implements Player {
		@Override
		public void visitZhuang(ZhuangHero element) {
			System.out.println("玩家-我,访问庄周，庄周开始使出技能");
			element.operate();
		}

		@Override
		public void visitZhen(ZhenHero element) {
			System.out.println("玩家-我,访问甄姬，甄姬开始使出技能");
			element.operate();
		}
	}

	public static class PlayerOthers implements Player {
		@Override
		public void visitZhuang(ZhuangHero element) {
			System.out.println("玩家-其他人,访问庄周，庄周开始使出技能");
			element.operate();
		}

		@Override
		public void visitZhen(ZhenHero element) {
			System.out.println("玩家-其他人,访问甄姬，甄姬开始使出技能");
			element.operate();
		}
	}

	public static class ObjectStructure {
		// 保存所有需要被访问的元素
		private List<Hero> heros = new ArrayList<Hero>();

		public void handleRequest(Player visitor) {
			// 访问所有元素
			for (Hero hero : heros) {
				hero.accept(visitor);
			}
		}

		public void addHero(Hero hero) {
			heros.add(hero);
		}
	}

	public static void main(String[] args) {
		ObjectStructure os = new ObjectStructure();
		Hero zhuang = new ZhuangHero();
		Hero zhen = new ZhenHero();

		os.addHero(zhuang);
		os.addHero(zhen);

		Player visitorMe = new PlayerMe();
		Player visitorOthers = new PlayerOthers();
		// 让访问者访问对象结构中的元素
		os.handleRequest(visitorMe);
		os.handleRequest(visitorOthers);
	}

//作者：愚公要移山
//链接：https://juejin.cn/post/6844903924630028295
//来源：掘金
//著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
}
